package com.qqbot.listener;

import com.alibaba.fastjson.JSONObject;
import com.qqbot.annotation.GroupAnnotation;
import com.qqbot.enums.DatePattern;
import com.qqbot.enums.GroupUserStatusEnum;
import com.qqbot.enums.StatusEnum;
import com.qqbot.exception.BusinessException;
import com.qqbot.model.group.Groups;
import com.qqbot.model.group.UserGroupRelation;
import com.qqbot.service.group.GroupsService;
import com.qqbot.service.group.UserGroupRelationService;
import com.qqbot.service.user.UserService;
import com.qqbot.utils.*;
import com.qqbot.vo.MusicVo;
import lombok.extern.slf4j.Slf4j;
import love.forte.simboot.annotation.*;
import love.forte.simboot.filter.MultiFilterMatchType;
import love.forte.simbot.component.mirai.MiraiGroup;
import love.forte.simbot.component.mirai.MiraiMember;
import love.forte.simbot.component.mirai.event.*;
import love.forte.simbot.component.mirai.message.MiraiMusicShare;
import love.forte.simbot.definition.Group;
import love.forte.simbot.definition.GroupInfo;
import love.forte.simbot.definition.GroupMember;
import love.forte.simbot.definition.Member;
import love.forte.simbot.event.EventResult;
import love.forte.simbot.event.GroupMessageEvent;
import love.forte.simbot.utils.item.Items;
import net.mamoe.mirai.message.data.MusicKind;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.MalformedURLException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 群事件
 *
 * @author 付亚全
 */
@Component
@Slf4j
public class GroupListener {

    @Resource
    private UserService userService;

    @Resource
    private GroupsService groupsService;

    @Resource
    private UserGroupRelationService userGroupRelationService;

    /**
     * 监听群消息
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    public EventResult listenerMessage(GroupMessageEvent event) throws BusinessException {
        String qq = event.getAuthor().getId().toString();
        String groupId = event.getGroup().getId().toString();
        log.info("GroupListener.listenerMessage.params=====>group:{},qq:{}", groupId, qq);
        String date = DateFormatUtil.format(new Date(), DatePattern.YYYY_MM_DD);
        RedisUtil.incrementScore(groupId + ":" + date, qq, Double.valueOf(1));
        return EventResult.of();
    }

    /**
     * chatGPT
     *
     * @param event
     * @param question
     * @return
     */
    @Listener
    @Filter(value = "/q{{question}}")
    public EventResult chatGPT(GroupMessageEvent event, @FilterValue("question") String question) {
        String groupId = event.getGroup().getId().toString();
        String date = DateFormatUtil.format(new Date(), DatePattern.YYYY_MM_DD);
        Set<String> set = RedisUtil.reverseRange(groupId + ":" + date, 0, 9);
        if (!event.getAuthor().isAdmin() && !set.contains(event.getAuthor().getId().toString())) {
            return EventResult.of();
        }
        question = question.replace(" ", "");
        log.info("GroupListener.chatGPT.params=====>sender:{},question:{}", event.getAuthor().getId(), question);
        String json = HttpUtil.httpGet("http://ovoa.cc/api/ChatGPT.php?msg=" + question + "&type=wifi&id=" + groupId);
        event.replyAsync(json);
        return EventResult.of();
    }

    /**
     * 活跃排行
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filter(value = "活跃排行")
    public EventResult activeRank(GroupMessageEvent event) throws BusinessException {
        String groupId = event.getGroup().getId().toString();
        log.info("GroupListener.activeRank.params=====>group:{},qq:{}", groupId);
        String date = DateFormatUtil.format(new Date(), DatePattern.YYYY_MM_DD);
        Set<String> set = RedisUtil.reverseRange(groupId + ":" + date, 0, 9);
        String str = set.stream().collect(Collectors.joining("\n"));
        event.replyBlocking(str);
        return EventResult.of();
    }

    /**
     * 禁言
     *
     * @param event
     * @param qq
     * @param duration
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filter(value = "禁言/{{qq}}/{{duration}}")
    public EventResult mute(GroupMessageEvent event, @FilterValue("qq") String qq, @FilterValue("duration") Long duration) {
        log.info("GroupListener.mute.params=====>sender:{},muteQQ:{},duration:{}", event.getAuthor().getId(), qq.trim(), duration);
        GroupMember member = SimbotUtil.getGroupMember(event, qq);
        //执行失败放行
        if (Objects.isNull(member)) {
            return EventResult.of();
        }
        boolean result = member.muteBlocking(duration, TimeUnit.MINUTES);
        log.info("GroupListener.mute.result=====>sender:{},muteQQ:{},duration:{},result:{}", event.getAuthor().getId(), member.getId(), duration, result);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 解除禁言
     *
     * @param event
     * @param qq
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "jc/{{qq}}"), @Filter(value = "解除禁言/{{qq}}")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult unMute(GroupMessageEvent event, @FilterValue("qq") String qq) {
        log.info("GroupListener.unMute.params=====>sender:{},umMuteQQ:{}", event.getAuthor().getId(), qq.trim());
        GroupMember member = SimbotUtil.getGroupMember(event, qq);
        //执行失败放行
        if (Objects.isNull(member)) {
            return EventResult.of();
        }
        boolean result = member.unmuteBlocking();
        log.info("GroupListener.unMute.result=====>sender:{},umMuteQQ:{},result:{}", event.getAuthor().getId(), member.getId(), result);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 开启全体禁言
     *
     * @param event
     * @return
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "全体禁言"), @Filter(value = "开启全体禁言")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult allMute(GroupMessageEvent event) {
        log.info("GroupListener.allMute.params=====>sender:{}", event.getAuthor().getId());
        boolean result = event.getGroup().muteBlocking();
        log.info("GroupListener.allMute.result=====>sender:{},result:{}", event.getAuthor().getId(), result);
        return EventResult.truncate();
    }

    /**
     * 关闭全体禁言
     *
     * @param event
     * @return
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "关闭禁言"), @Filter(value = "关闭全体禁言")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult allUnMute(GroupMessageEvent event) {
        log.info("GroupListener.allUnMute.params=====>sender:{}", event.getAuthor().getId());
        boolean result = event.getGroup().unmuteBlocking();
        log.info("GroupListener.allUnMute.result=====>sender:{},result:{}", event.getAuthor().getId(), result);
        return EventResult.truncate();
    }

    /**
     * 踢人
     *
     * @param event
     * @param qq
     * @return
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "t/{{qq}}"), @Filter(value = "T/{{qq}}"), @Filter(value = "踢/{{qq}}")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult kick(GroupMessageEvent event, @FilterValue("qq") String qq) throws BusinessException {
        log.info("GroupListener.kick.params=====>sender:{},kickQQ:{}", event.getAuthor().getId(), qq.trim());
        GroupMember member = SimbotUtil.getGroupMember(event, qq);
        //执行失败放行
        if (Objects.isNull(member)) {
            return EventResult.of();
        }
        MiraiMember miraiMember = (MiraiMember) member;
        boolean result = miraiMember.kickBlocking(Constant.GROUP_RULE_MESSAGE);
        //加入黑名单
        if (result) {
            userGroupRelationService.saveOrUpdateGroupUser(event.getBot().getId().toString(), miraiMember.getId().toString(), event.getGroup().getId().toString(), GroupUserStatusEnum.BLACKLIST.getCode(), null);
        }
        log.info("GroupListener.kick.result=====>sender:{},kickQQ:{},result:{}", event.getAuthor().getId(), member.getId(), result);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 设置群昵称
     *
     * @param event
     * @param qq
     * @param nickName
     * @return
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "昵称/{{qq}}/{{nickName}}"), @Filter(value = "设置昵称/{{qq}}/{{nickName}}")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult setNckName(GroupMessageEvent event, @FilterValue("qq") String qq, @FilterValue("nickName") String nickName) {
        log.info("GroupListener.setNckName.params=====>sender:{},qq:{},nickName:{}", event.getAuthor().getId(), qq.trim(), nickName);
        GroupMember member = SimbotUtil.getGroupMember(event, qq);
        //执行失败放行
        if (Objects.isNull(member)) {
            return EventResult.of();
        }
        MiraiMember miraiMember = (MiraiMember) member;
        miraiMember.setNickname(nickName);
        log.info("GroupListener.setNckName.result=====>sender:{},qq:{},nickName:{},result:{}", event.getAuthor().getId(), member.getId(), nickName, true);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 设置群头衔
     *
     * @param event
     * @param qq
     * @param specialTitle
     * @return
     */
    @Listener
    @GroupAnnotation(value = true)
    @Filters(value = {@Filter(value = "头衔/{{qq}}/{{specialTitle}}"), @Filter(value = "设置头衔/{{qq}}/{{specialTitle}}")}, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult setSpecialTitle(GroupMessageEvent event, @FilterValue("qq") String qq, @FilterValue("specialTitle") String specialTitle) {
        log.info("GroupListener.setSpecialTitle.params=====>sender:{},qq:{},specialTitle:{}", event.getAuthor().getId(), qq.trim(), specialTitle);
        GroupMember member = SimbotUtil.getGroupMember(event, qq);
        //执行失败放行
        if (Objects.isNull(member)) {
            return EventResult.of();
        }
        MiraiMember miraiMember = (MiraiMember) member;
        miraiMember.setSpecialTitle(specialTitle);
        log.info("GroupListener.setSpecialTitle.result=====>sender:{},qq:{},specialTitle:{},result:{}", event.getAuthor().getId(), member.getId(), specialTitle, true);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 我要头衔
     *
     * @param event
     * @param specialTitle
     * @return
     */
    @Listener
    @Filter(value = "我要头衔/{{specialTitle}}")
    public EventResult iNeedSpecialTitle(GroupMessageEvent event, @FilterValue("specialTitle") String specialTitle) {
        log.info("GroupListener.iNeedSpecialTitle.params=====>sender:{},specialTitle:{}", event.getAuthor().getId(), specialTitle);
        Member member = event.getAuthor();
        MiraiMember miraiMember = (MiraiMember) member;
        miraiMember.setSpecialTitle(specialTitle);
        log.info("GroupListener.iNeedSpecialTitle.result=====>sender:{},specialTitle:{},result:{}", event.getAuthor().getId(), specialTitle, true);
        //执行成功阻断
        return EventResult.truncate();
    }

    /**
     * 点歌
     *
     * @param event
     * @param music
     * @return
     */
    @Listener
    @Filter(value = "点歌/{{music}}")
    public EventResult songs(GroupMessageEvent event, @FilterValue("music") String music) {
        String groupId = event.getGroup().getId().toString();
        String date = DateFormatUtil.format(new Date(), DatePattern.YYYY_MM_DD);
        Set<String> set = RedisUtil.reverseRange(groupId + ":" + date, 0, 9);
        if (!event.getAuthor().isAdmin() && !set.contains(event.getAuthor().getId().toString())) {
            return EventResult.of();
        }
        music = music.replace(" ", "");
        log.info("GroupListener.songs.params=====>sender:{},music:{}", event.getAuthor().getId(), music);
        String json = HttpUtil.httpGet("https://xiaoapi.cn/API/yy_sq.php?msg=" + music + "&type=json&n=1");
        MusicVo vo = JSONObject.parseObject(json, MusicVo.class);
        MiraiMusicShare miraiMusicShare = new MiraiMusicShare(MusicKind.NeteaseCloudMusic, vo.getName(), vo.getSinger(), vo.getUrl(), vo.getCover(), vo.getUrl());
        event.getSource().sendAsync(miraiMusicShare);
        return EventResult.truncate();
    }


    /**
     * 查询群成员积分
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    @GroupAnnotation
    @Filters(value = {
            @Filter(value = "积分查询"),
            @Filter(value = "查询积分")
    }, multiMatchType = MultiFilterMatchType.ANY)
    public EventResult queryIntegral(GroupMessageEvent event) throws BusinessException {
        Member member = event.getAuthor();
        Group group = event.getGroup();
        String bot = event.getBot().getId().toString();
        log.info("GroupListener.queryIntegral.params=====>sender:{},groupNo:{}", member.getId(), group.getId());
        UserGroupRelation relation = userGroupRelationService.getByQqAndGroupNo(bot, member.getId().toString(), group.getId().toString());
        if (Objects.isNull(relation)) {
            throw new BusinessException(group.getId() + "-" + member.getId() + Constant.GROUP_USER_NOT_FOUND_MESSAGE);
        }
        event.replyAsync("当前积分：" + relation.getIntegral());
        return EventResult.truncate();
    }

    /**
     * 积分排行
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    @GroupAnnotation
    @Filter(value = "积分排行")
    public EventResult integralRanking(GroupMessageEvent event) throws BusinessException {
        Member member = event.getAuthor();
        Group group = event.getGroup();
        String bot = event.getBot().getId().toString();
        log.info("GroupListener.integralRanking.params=====>sender:{},groupNo:{}", member.getId(), group.getId());
        List<UserGroupRelation> list = userGroupRelationService.integralRanking(bot, group.getId().toString());
        String str = "积分排行榜\n";
        for (UserGroupRelation relation : list) {
            str += relation.getQq() + "——" + relation.getIntegral() + "\n";
        }
        event.getSource().sendBlocking(str);
        return EventResult.truncate();
    }

    /**
     * 入群请求事件
     *
     * @param event
     * @return
     */
    @Listener
    public EventResult joinGroupRequestEvent(MiraiMemberJoinRequestEvent event) throws BusinessException {
        RequestMemberInfo memberInfo = event.getRequester();
        GroupInfo group = event.getGroup();
        log.info("GroupListener.joinGroupRequestEvent.params=====>group:{}-{},qq:{}", group.getId(), group.getName(), memberInfo.getId());
        boolean result = userGroupRelationService.isItBlacklist(event.getBot().getId().toString(), memberInfo.getId().toString(), group.getId().toString());
        log.info("GroupListener.joinGroupRequestEvent.result=====>{}", result);
        //如果是黑名单则直接拒绝
        if (result) {
            event.rejectBlocking(Constant.GROUP_REJECT_MESSAGE);
            return EventResult.of();
        }
        event.acceptBlocking();
        return EventResult.of();
    }

    /**
     * 机器人受邀入群请求事件
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    public EventResult botInvitedJoinGroupEvent(MiraiBotInvitedJoinGroupRequestEvent event) throws BusinessException {
        GroupInfo group = event.getGroup();
        InvitorUserInfo inviter = event.getInviter();
        log.info("GroupListener.botInvitedJoinGroupEvent.params=====>group:{}-{},inviter:{}", group.getId(), group.getName(), inviter.getId());
        boolean result = userService.isItMaster(event.getBot().getId().toString(), inviter.getId().toString());
        log.info("GroupListener.joinGroupRequestEvent.result=====>{}", result);
        if (!result) {
            event.rejectBlocking();
            throw new BusinessException("邀请人" + Constant.NO_PERMISSION);
        }
        event.acceptBlocking();
        return EventResult.of();
    }

    /**
     * 机器人入群事件
     *
     * @param event
     * @return
     * @throws BusinessException
     */
    @Listener
    public EventResult botJoinGroupEvent(MiraiBotJoinGroupEvent event) throws BusinessException {
        MiraiGroup group = event.getGroup();
        MiraiMember operator = event.getOperator();
        String bot = event.getBot().getId().toString();
        String groupNo = group.getId().toString();
        if (Objects.nonNull(operator) && !userService.isItMaster(bot, operator.getId().toString())) {
            boolean result = group.deleteBlocking();
            log.info("GroupListener.botJoinGroupEvent.quit=====>result:{}", result);
            throw new BusinessException("邀请人" + Constant.NO_PERMISSION);
        }
        log.info("GroupListener.botJoinGroupEvent.params=====>group:{}-{},inviter:{}", groupNo, group.getName(), JsonUtil.toJson(operator));
        //保存当前群信息
        boolean groupResult = groupsService.saveGroup(bot, groupNo, StatusEnum.TRUE.getCode());
        //保存当前群所有成员信息
        Items<MiraiMember> members = group.getMembers();
        List<UserGroupRelation> list = new ArrayList<>();
        List<String> qqList = new ArrayList<>();
        members.asStream().forEach(member -> {
            UserGroupRelation relation = new UserGroupRelation();
            String qq = member.getId().toString();
            relation.setBot(bot);
            relation.setQq(qq);
            relation.setGroupNo(groupNo);
            relation.setStatus(GroupUserStatusEnum.NORMAL.getCode());
            list.add(relation);
            qqList.add(qq);
        });
        log.info("GroupListener.botJoinGroupEvent.list=====>{}", JsonUtil.toJson(list));
        Map<String, UserGroupRelation> map = userGroupRelationService.listByGroupAndQqList(bot, groupNo, qqList).stream().collect(Collectors.toMap(UserGroupRelation::getQq, Function.identity(), (key1, key2) -> key1));
        //保存群成员信息
        if (map.isEmpty()) {
            boolean result = userGroupRelationService.saveBatch(list);
            log.info("GroupListener.botJoinGroupEvent.result=====>groupResult:{},saveBatch:{}}", groupResult, result);
            return EventResult.of();
        }
        //更新群成员信息
        List<String> filterQq = qqList.stream().filter(map::containsKey).collect(Collectors.toList());
        boolean result = userGroupRelationService.updateStatusByGroupAndQqList(groupNo, filterQq);
        log.info("GroupListener.botJoinGroupEvent.result=====>groupResult:{},updateStatusByGroupAndQQList:{}}", groupResult, result);
        return EventResult.of();
    }

    /**
     * 入群事件
     *
     * @param event
     * @return
     */
    @Listener
    public EventResult joinGroupEvent(MiraiMemberJoinEvent event) throws BusinessException, MalformedURLException {
        MiraiMember member = event.getMember();
        MiraiGroup group = event.getGroup();
        String bot = event.getBot().getId().toString();
        String qq = member.getId().toString();
        String groupNo = event.getGroup().getId().toString();
        log.info("GroupListener.joinGroupEvent.params=====>group:{}-{},qq:{}", groupNo, group.getName(), qq);
        userGroupRelationService.saveOrUpdateGroupUser(bot, qq, groupNo, GroupUserStatusEnum.NORMAL.getCode(), null);
        Groups groups = groupsService.getByGroupNo(bot, groupNo);
        if (Objects.nonNull(groups) && groups.getWelcome()) {
            SimbotUtil.joinGroupTextWelcome(group, member, groups.getWelcomeContent());
        }
        return EventResult.of();
    }

    /**
     * 退群事件
     *
     * @param event
     * @return
     */
    @Listener
    public EventResult leaveGroupEvent(MiraiMemberLeaveEvent event) throws BusinessException {
        MiraiMember member = event.getMember();
        MiraiGroup group = event.getGroup();
        log.info("GroupListener.leaveGroupEvent.params=====>group:{}-{},qq:{}", group.getId(), group.getName(), member.getId());
        userGroupRelationService.saveOrUpdateGroupUser(event.getBot().getId().toString(), member.getId().toString(), group.getId().toString(), GroupUserStatusEnum.LEAVE.getCode(), null);
        return EventResult.of();
    }


}
